package com.lenovo.tool;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;

import javax.xml.transform.sax.TransformerHandler;

import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;


class XmlResUtil {
    private static final String TAG_RESOURCES = "resources";
    private static final String TAG_STRING = "string";
    private static final String TAG_STRING_ARRAY = "string-array";
    private static final String TAG_PLURALS = "plurals";

    private static final String NEW_LINE = "\n";

    private static String getElementKeyName(String prefix, Element element,
            boolean ignoreMsgIdAndTool) {
        NamedNodeMap map = element.getAttributes();
        String[] nodes = new String[map.getLength()];

        for (int k = 0; k < map.getLength(); k++) {
            Node n = map.item(k);
            String attrName = n.getNodeName();
            String attrValue = n.getTextContent();
            nodes[k] = attrName + "." + attrValue;
        }
        Arrays.sort(nodes);

        StringBuffer sb = new StringBuffer();
        sb.append(prefix);
        for (int k = 0; k < nodes.length; k++) {
            // ignore msg id attribute added by MTK
            if (ignoreMsgIdAndTool) {
                if (nodes[k].startsWith("msgid.") || nodes[k].startsWith("tools:ignore.")) {
                    continue;
                }
            }
            sb.append(".");
            sb.append(nodes[k]);
        }

        return sb.toString();
    }

    private static void analyzeElements(HashMap<String, Element> map,
            Element root, String tagName, HashSet<String> excludeNames) {
        NodeList nodeList = root.getElementsByTagName(tagName);
        for (int i = 0; i < nodeList.getLength(); i++) {
            Element element = (Element) nodeList.item(i);

            String name = element.getAttribute("name");
            // Filter out specified elements
            if (excludeNames != null && excludeNames.contains(name)) {
                continue;
            }
            
            if (TAG_STRING_ARRAY.equals(element.getTagName())) {
                boolean needTranslation = false;

                NodeList children = element.getElementsByTagName("item");
                for (int k = 0; k < children.getLength(); k++) {
                    Node node = children.item(k).getFirstChild();
                    if (node != null) {
                        String value = node.getNodeValue();
                        if (value != null && !(value.startsWith("@string/"))) {
                            needTranslation = true;
                            if (needTranslation) {
                                break;
                            }
                        }
                    }
                }

                if (!needTranslation) {
                    continue;
                }
            }

            String translatable = element.getAttribute("translatable");
            if (translatable == null || !(translatable.trim().equals("false"))) {
                String comment = null;
                Node node = element.getPreviousSibling();
                while (node != null && node instanceof Text) {
                    node = node.getPreviousSibling();
                }

                if (node instanceof Comment) {
                    comment = node.getNodeValue();
                }

                if (comment == null || !comment.contains("Do not translate")) {
                    String keyName = getElementKeyName(tagName, element, true);
                    map.put(keyName, element);
                }
            }
        }
    }

    public static HashMap<String, Element> parseXml(Document document) {

        HashMap<String, Element> map = new HashMap<String, Element>();
        Element root = document.getDocumentElement();

        analyzeElements(map, root, TAG_STRING, null);
        analyzeElements(map, root, TAG_STRING_ARRAY, null);
        analyzeElements(map, root, TAG_PLURALS, null);

        return map;
    }

    public static HashMap<String, Element> parseXml(Document document,
            HashSet<String> excludeArrays) {

        HashMap<String, Element> map = new HashMap<String, Element>();
        Element root = document.getDocumentElement();

        analyzeElements(map, root, TAG_STRING, null);
        analyzeElements(map, root, TAG_STRING_ARRAY, excludeArrays);
        analyzeElements(map, root, TAG_PLURALS, null);

        return map;
    }

    public static void transformNode(boolean isSameLine, TransformerHandler th, Node node,
            HashMap<String, AttributesImpl> attrMap, String prefix)
            throws SAXException {
        if (node instanceof Document) {
            th.startDocument();
            th.characters(NEW_LINE.toCharArray(), 0, NEW_LINE.length());

            NodeList childList = node.getChildNodes();
            for (int k = 0; k < childList.getLength(); k++) {
                transformNode(isSameLine, th, childList.item(k), attrMap, null);
            }

            th.endDocument();
        } else if (node instanceof Element) {
            String tagName = ((Element) node).getTagName();

            StringBuffer sb = new StringBuffer();
            if (prefix != null && prefix.trim().length() != 0) {
                sb.append(prefix.trim());
                sb.append(".");
            }
            sb.append(tagName);

            String keyName = getElementKeyName(sb.toString(), (Element) node,
                    false);

            if (attrMap.containsKey(keyName)) {
                th.startElement("", "", tagName, attrMap.get(keyName));
            } else {
                th.startElement("", "", tagName, new AttributesImpl());
            }

            if (isSameLine && TAG_RESOURCES.equals(tagName)) {
                th.characters(NEW_LINE.toCharArray(), 0, NEW_LINE.length());
            }

            NodeList childList = node.getChildNodes();
            for (int k = 0; k < childList.getLength(); k++) {
                transformNode(isSameLine, th, childList.item(k), attrMap, sb.toString());
            }

            th.endElement("", "", tagName);

//            if (TAG_RESOURCES.equals(tagName)) {
//                th.characters(NEW_LINE.toCharArray(), 0, NEW_LINE.length());
//            }
        } else if (node instanceof Comment) {
            String nodeValue = node.getNodeValue();
            if (nodeValue != null) {
                th.comment(nodeValue.toCharArray(), 0, nodeValue.length());
            }
        } else {
            String nodeValue = node.getNodeValue();
            if (nodeValue != null) {
                th.characters(nodeValue.toCharArray(), 0, nodeValue.length());
            }
        }
    }
    
    public static boolean createNewFile(File file) {
        if (file.exists()) {
            return true;
        }

        File path = file.getParentFile();
        ArrayList<File> list = new ArrayList<File>();
        while (path != null && !path.exists()) {
            list.add(path);
            path = path.getParentFile();
        }

        if (path == null) {
            return false;
        }

        for (int k = list.size() - 1; k >= 0; k--) {
            if (list.get(k).mkdir() == false) {
                return false;
            }
        }

        try {
            return file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();

            return false;
        }
    }

    public static File getAssociatedFile(File file) throws IOException {
        String name = file.getName();
        String[] files = FileFilter.getInstance().getAllFiles();
        for (String fileName : files)
		{
			if(fileName.equals(name))
			{
				 return new File(file.getParentFile(), fileName);
			}
		}
        return null;
    }

    public static void copyFile(File sourceFile, File targetFile)
            throws IOException {
        BufferedInputStream inBuff = null;
        BufferedOutputStream outBuff = null;
        try {
            inBuff = new BufferedInputStream(new FileInputStream(sourceFile));
    
            outBuff = new BufferedOutputStream(new FileOutputStream(targetFile));
    
            byte[] b = new byte[1024 * 5];
            int len;
            while ((len = inBuff.read(b)) != -1) {
                outBuff.write(b, 0, len);
            }
            outBuff.flush();
        } finally {
            if (inBuff != null)
                inBuff.close();
            if (outBuff != null)
                outBuff.close();
        }
    }

}
